package org.filter4osgi.builder.testing;

import org.filter4osgi.builder.FilterBuilder;
import static org.filter4osgi.builder.FilterBuilder.*;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

import java.util.Hashtable;

/**
 * This class tests that the FilterBuilder bundle was loaded correctly.
 *
 * @author Hamlet D'Arcy
 */
public class ActivatorForTesting implements BundleActivator {
    @Override
    public void start(BundleContext context) throws Exception {

        Object englishEmail = registerMockService(context, "email", "EN_US");
        Object germanEmail = registerMockService(context, "email", "DE");
        Object frenchEmail = registerMockService(context, "email", "FR");
        Object englishSMS = registerMockService(context, "sms", "EN_US");
        Object germanSMS = registerMockService(context, "sms", "DE");
        Object frenchSMS = registerMockService(context, "sms", "FR");
        Object englishTwitter = registerMockService(context, "twitter", "EN_US");
        Object germanTwitter = registerMockService(context, "twitter", "DE");
        Object frenchTwitter = registerMockService(context, "twitter", "FR");

        assertFilterContains(context,
                or(
                        and(
                                eq("mailbox", "email"),
                                eq("lang", "EN_US")
                        ),
                        and(
                                eq("mailbox", "sms"),
                                eq("lang", "FR")
                        )
                ),
                englishEmail, frenchSMS);

        assertFilterContains(context,
                eq("mailbox", "sms"),
                englishSMS, germanSMS, frenchSMS);

        assertFilterContains(context,
                and(
                        not(
                                eq("mailbox", "sms")
                        ),
                        not(
                                eq("mailbox", "email")
                        )
                ),
                englishTwitter, germanTwitter, frenchTwitter);

        assertFilterContains(context,
                and(
                        eq("mailbox", "email"),
                        not(
                                eq("lang", "EN_US")
                        )
                ),
                germanEmail, frenchEmail);

        System.out.println("ActivatorForTesting: Self-diagnosis successful!");
    }

    private static void assertFilterContains(BundleContext context, FilterBuilder filter, Object... services) throws InvalidSyntaxException {

        ServiceReference[] serviceRefs = context.getAllServiceReferences(String.class.getName(), filter.toString());

        // make sure correct # services were retrieved.
        assertEquals(services.length, serviceRefs.length);

        for (int x = 0; x < services.length; x++) {
            ServiceReference serviceReference = serviceRefs[x];
            Object service = context.getService(serviceReference);
            assertEquals(service, service);
            context.ungetService(serviceReference);
        }
    }

    private static void assertEquals(Object expected, Object actual) {
        if (expected == null && actual == null) return;
        if (expected == null || actual == null || !expected.equals(actual)) {
            throw new RuntimeException("Values not equal. Expected: " + expected + " Actual: " + actual);
        }
    }

    private Object registerMockService(BundleContext context, final String name, final String language) {
        String service = "Mock Service. mailbox: " + name + " language: " + language;
        context.registerService(
                String.class.getName(),
                service,
                new Hashtable<String, String>() {{
                    put("mailbox", name);
                    put("lang", language);
                }}
        );
        return service;
    }

    @Override
    public void stop(BundleContext context) throws Exception {

    }
}
